from skillchallenge.models import *
import EventEngine
import CodeEngine

class ChatEngine:
   
    BEGIN_CHAT = 'CHAT_BEGIN'
    END_CHAT = 'CHAT_END'
    CHAT = 'CHAT'
    INTERRUPT_CHAT = 'CHAT_INTERRUPT'
   
    codeEngine = CodeEngine.CodeEngine()
    event_engine = EventEngine.EventEngine()
    
    def is_chatting(self):
        e = self.event_engine.fired_by_info('CHAT')
        if e and e.latest():
            return (self.END_CHAT not in e.latest().info) and (self.INTERRUPT_CHAT not in e.latest().info)
        else:
            return False
    
    def create_beginning_chat(self, speaker, listener, text='', reply=''):
        return Speech.objects.create(begin=True, speaker=speaker, listener=listener, text=text, reply=reply)
    
    def create_branch_chat(self, speaker, listener, text='', reply=''):
        return Speech.objects.create(speaker=speaker, listener=listener, text=text, reply=reply)
    
    def create_end_branch_chat(self, speaker, listener, text='', reply=''):
        return Speech.objects.create(speaker=speaker, listener=listener, end=True, text=text, reply=reply)
    
    def begin_event(self, speech, precons):
        a1 = self.codeEngine.create_message_action('you start to talk with ' + speech.listener.name.text + '.')
        e = self.eventize(speech)
        e.actions.add(a1)
        e.preconditions = precons
        e.save()
        return e
    
    def engage(self, event_id, object_id, char_id):
        speech = Speech.objects.get(id=object_id)
        
        if speech.begin:
            self.add_interrupt_event(speech)
        
        if speech.end or speech.interrupt: 
            self.remove_interrupt_event()
        
        others = self.event_engine.player_available().filter(info__istartswith='chat').exclude(info__istartswith=self.INTERRUPT_CHAT).exclude(id= event_id)
        for e in others:
            self.event_engine.fire_fail(e)
        if speech:
            for sp in speech.branches.all():
                self.eventize(sp)

    def remove_interrupt_event(self):
        interrupts = self.event_engine.player_available().filter(info__istartswith=self.INTERRUPT_CHAT)
        if interrupts and interrupts.latest():
            self.event_engine.fire_fail(interrupts.latest())
    
    def add_interrupt_event(self, speech):
        if not self.event_engine.player_available().filter(info__istartswith=self.INTERRUPT_CHAT):
            a1 = self.codeEngine.create_message_action('you interrupt the chat with ' + speech.listener.name.text + '.')
            e = self.event_engine.add_event(player_will = True, actions = [a1],
                                            description=('interrupt chat with ' + speech.listener.name.text + '.'),
                                            info = self.__info__(speech, True),
                                            online=True, chatting=True)
    
    def eventize(self, speech):
        a1 = self.codeEngine.create_message_action('you say to ' + speech.listener.name.text + ': ' + speech.text + '.')
        a2 = self.codeEngine.create_message_action(speech.listener.name.text + ' says to you: ' + speech.reply + '.')

        e = self.event_engine.add_event(player_will = True, description=('say to ' + speech.listener.name.text + ': "' + speech.text + '"'),
                                          info = self.__info__(speech),
                                          online=True, chatting=True)
        
        a3 = self.codeEngine.engage_engine_action('global_chat_engine', e.id, speech.id)
        e.actions = [a1, a2, a3]
        return e
    
    def __info__(self, speech, interrupt=False):
        type = ''
        if interrupt:
            type = self.INTERRUPT_CHAT
        else:
            if speech.begin:
                type = self.BEGIN_CHAT
            else:
                if speech.end:
                    type = self.END_CHAT
                else:
                    type = self.CHAT
        
        return type + ':' + speech.info + ':' + str(speech.speaker.id) + ':' + str(speech.listener.id)
            